﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.Revit;

namespace YArchitech.Public
{
	public class DetermineTwoDuctsAlignment
	{
		public bool IsTopAlign
		{
			get
			{
				if (!this.IsVertical())
				{
					if (!this.IsParallel())
					{
						return false;
					}
					this.isTopAlign = this.IsTopAlignByTwoParallelDucts();
				}
				else
				{
					this.isTopAlign = this.IsTopAlignByTwoVerticalDucts();
				}
				return this.isTopAlign;
			}
		}

		public bool IsBottomAlign
		{
			get
			{
				if (!this.IsVertical())
				{
					if (!this.IsParallel())
					{
						return false;
					}
					this.isBottomAlign = this.IsBottomAlignByTwoParallelDucts();
				}
				else
				{
					this.isBottomAlign = this.IsBottomAlignByTwoVerticalDucts();
				}
				return this.isBottomAlign;
			}
		}

		public bool IsVerticalMiddleAlign
		{
			get
			{
				if (!this.IsVertical())
				{
					if (!this.IsParallel())
					{
						return false;
					}
					this.isVerticalMiddleAlign = this.IsVerticalMiddleAlignByTwoParallelDucts();
				}
				else
				{
					this.isVerticalMiddleAlign = this.IsVerticalMiddleAlignByTwoVerticalDucts();
				}
				return this.isVerticalMiddleAlign;
			}
		}

		public bool IsLeftAlign
		{
			get
			{
				if (!this.IsParallel())
				{
					return false;
				}
				this.isLeftAlign = this.IsLeftAlignByTwoParallelDucts();
				return this.isLeftAlign;
			}
		}

		public bool IsRightAlign
		{
			get
			{
				if (!this.IsParallel())
				{
					return false;
				}
				this.isRightAlign = this.IsRightAlignByTwoParallelDucts();
				return this.isRightAlign;
			}
		}

		public bool IsHorizontalMiddleAlign
		{
			get
			{
				if (!this.IsParallel())
				{
					return false;
				}
				this.isHorizontalMiddleAlign = this.IsHorizontalMiddleAlignByTwoParallelDucts();
				return this.isHorizontalMiddleAlign;
			}
		}

		public DetermineTwoDuctsAlignment(XYZ baseVector, Duct ductA, Duct ductB)
		{
			this._ductA = ductA;
			this._ductB = ductB;
			this._baseVector = baseVector;
			this.GetTwoDuctsCloserConnector();
			this.GetDuctAPoints();
		}

		private bool IsParallel()
		{
			return new YJKPiping<Duct>(this._ductA).IsParallel(this._ductB);
		}

		private bool IsVertical()
		{
			return new YJKPiping<Duct>(this._ductA).IsVertical(this._ductB);
		}

		private void GetTwoDuctsCloserConnector()
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(this._ductA);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(this._ductB);
			this.ductAConn = hypiping.GetCloseConnector(hypiping2.StartConnector.Origin, false);
			this.ductBConn = hypiping2.GetCloseConnector(hypiping.StartConnector.Origin, false);
		}

		private bool IsTheBaseVectorOk()
		{
			this.basicX = null;
			this.basicY = this.ductAConn.CoordinateSystem.BasisY;
			if (!this._baseVector.Normalize().IsAlmostEqualTo(this.ductAConn.CoordinateSystem.BasisZ, 0.0001))
			{
				if (!this._baseVector.Normalize().IsAlmostEqualTo(-this.ductAConn.CoordinateSystem.BasisZ, 0.0001))
				{
					return false;
				}
				this.basicX = -this.ductAConn.CoordinateSystem.BasisX;
			}
			else
			{
				this.basicX = this.ductAConn.CoordinateSystem.BasisX;
			}
			return true;
		}

		private void GetDuctAPoints()
		{
			if (!this.IsTheBaseVectorOk())
			{
				return;
			}
			this.leftTop = this.ductAConn.Origin + this.basicX * (-this.ductAConn.Width / 2.0) + this.basicY * (-this.ductAConn.Height / 2.0);
			this.rightTop = this.ductAConn.Origin + this.basicX * this.ductAConn.Width / 2.0 + this.basicY * (-this.ductAConn.Height / 2.0);
			this.rightBottom = this.ductAConn.Origin + this.basicX * this.ductAConn.Width / 2.0 + this.basicY * (this.ductAConn.Height / 2.0);
			this.rightMiddle = this.ductAConn.Origin + this.basicX * (this.ductAConn.Width / 2.0);
			this.topMiddle = this.ductAConn.Origin + this.basicY * (-this.ductAConn.Height / 2.0);
		}

		private bool IsTopAlignByTwoVerticalDucts()
		{
			Line line = Line.CreateUnbound(this.rightTop, this.ductAConn.CoordinateSystem.BasisZ);
			XYZ xyz = this.ductBConn.Origin + this.basicY * (-this.ductBConn.Height / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this.basicX, 0.001) || xyz2.IsAlmostEqualTo(-this.basicX, 0.001);
		}

		private bool JudgeVectorBeZero(XYZ vector)
		{
			XYZ xyz = new XYZ(0.0, 0.0, 0.0);
			return vector.IsAlmostEqualTo(xyz, 0.0001);
		}

		private bool IsBottomAlignByTwoVerticalDucts()
		{
			Line line = Line.CreateUnbound(this.rightBottom, this.ductAConn.CoordinateSystem.BasisZ);
			XYZ xyz = this.ductBConn.Origin + this.basicY * (this.ductBConn.Height / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this.basicX, 0.001) || xyz2.IsAlmostEqualTo(-this.basicX, 0.001);
		}

		private bool IsVerticalMiddleAlignByTwoVerticalDucts()
		{
			Line line = Line.CreateUnbound(this.rightMiddle, this.ductAConn.CoordinateSystem.BasisZ);
			XYZ origin = this.ductBConn.Origin;
			XYZ xyz = (new YJKLine(line).GetProject(origin) - origin).Normalize();
			return this.JudgeVectorBeZero(xyz) || xyz.IsAlmostEqualTo(this.basicX, 0.001) || xyz.IsAlmostEqualTo(-this.basicX, 0.001);
		}

		private bool IsTopAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.rightTop, this.ductAConn.CoordinateSystem.BasisX);
			XYZ xyz = this.ductBConn.Origin + this.basicY * (-this.ductBConn.Height / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this._baseVector, 0.001) || xyz2.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		private bool IsBottomAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.rightBottom, this.ductAConn.CoordinateSystem.BasisX);
			XYZ xyz = this.ductBConn.Origin + this.basicY * (this.ductBConn.Height / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this._baseVector, 0.001) || xyz2.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		private bool IsVerticalMiddleAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.rightMiddle, this.ductAConn.CoordinateSystem.BasisX);
			XYZ origin = this.ductBConn.Origin;
			XYZ xyz = (new YJKLine(line).GetProject(origin) - origin).Normalize();
			return this.JudgeVectorBeZero(xyz) || xyz.IsAlmostEqualTo(this._baseVector, 0.001) || xyz.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		private bool IsLeftAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.leftTop, this.basicY);
			XYZ xyz = this.ductBConn.Origin + this.basicX * (-this.ductBConn.Width / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this._baseVector, 0.001) || xyz2.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		private bool IsRightAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.rightTop, this.basicY);
			XYZ xyz = this.ductBConn.Origin + this.basicX * (this.ductBConn.Width / 2.0);
			XYZ xyz2 = (new YJKLine(line).GetProject(xyz) - xyz).Normalize();
			return this.JudgeVectorBeZero(xyz2) || xyz2.IsAlmostEqualTo(this._baseVector, 0.001) || xyz2.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		private bool IsHorizontalMiddleAlignByTwoParallelDucts()
		{
			Line line = Line.CreateUnbound(this.topMiddle, this.basicY);
			XYZ origin = this.ductBConn.Origin;
			XYZ xyz = (new YJKLine(line).GetProject(origin) - origin).Normalize();
			return this.JudgeVectorBeZero(xyz) || xyz.IsAlmostEqualTo(this._baseVector, 0.001) || xyz.IsAlmostEqualTo(-this._baseVector, 0.001);
		}

		public List<Alignments> GetVerticalAlignmentsByTwoDucts()
		{
			List<Alignments> list = new List<Alignments>();
			if (this.IsTopAlign)
			{
				list.Add(Alignments.Top);
			}
			if (this.IsBottomAlign)
			{
				list.Add(Alignments.Bottom);
			}
			if (this.IsVerticalMiddleAlign)
			{
				list.Add(Alignments.VerticalMiddle);
			}
			return list;
		}

		public List<Alignments> GetHorizontalAlignmentsByTwoDucts()
		{
			List<Alignments> list = new List<Alignments>();
			if (this.IsLeftAlign)
			{
				list.Add(Alignments.Left);
			}
			if (this.IsRightAlign)
			{
				list.Add(Alignments.Right);
			}
			if (this.IsHorizontalMiddleAlign)
			{
				list.Add(Alignments.HorizontalMiddle);
			}
			return list;
		}

		private Duct _ductA;

		private Duct _ductB;

		private XYZ _baseVector;

		private XYZ basicX;

		private XYZ basicY;

		private Connector ductAConn;

		private Connector ductBConn;

		private XYZ leftTop;

		private XYZ rightTop;

		private XYZ rightBottom;

		private XYZ rightMiddle;

		private XYZ topMiddle;

		private bool isTopAlign;

		private bool isBottomAlign;

		private bool isVerticalMiddleAlign;

		private bool isLeftAlign;

		private bool isRightAlign;

		private bool isHorizontalMiddleAlign;
	}
}
